import backtrader as bt
import pandas as pd
import datetime
# 定义策略
class TestStrategy(bt.Strategy):
    params = (
        ('maperiod', 20),
    )

    def __init__(self):
        self.order = None
        self.ma = bt.indicators.SimpleMovingAverage(self.datas[0], period=self.params.maperiod)
        # 引用到输入数据的close价格
        self.dataclose = self.datas[0].close


    def log(self, txt, dt=None):
        ''' 提供记录功能'''
        dt = dt or self.datas[0].datetime.datetime(0)  # 使用 datetime 而不是 date
        # print('%s, %s' % (dt.isoformat(), txt))


    def notify_order(self, order):
        if order.status in [order.Submitted]:
            # 订单已提交，但尚未被经纪商接受
            self.log('ORDER SUBMITTED')
            self.order = order
        elif order.status in [order.Accepted]:
            # 订单已被经纪商接受，但尚未执行
            self.log('ORDER Accepted')
            self.order = order
        elif order.status in [order.Completed]:
            # 订单执行，并已完成
            if order.isbuy():
                self.log('BUY EXECUTED, %.2f' % order.executed.price)
            else:
                self.log('SELL EXECUTED, %.2f' % order.executed.price)
            self.order = None
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            # 订单被取消、保证金不足或拒绝
            self.log('ORDER CANCELED/MARGIN/REJECTED')
            self.order = None


    def next(self):
        # 判断是否有交易指令正在进行
        if(self.order):
            return
        
        # 空仓（当前没有持仓）
        if not self.position:
            if self.datas[0].close[0] > self.ma[0]:
                self.order = self.buy(size=200)  # 买入两百股
        else:
            if self.datas[0].close[0] < self.ma[0]:
                self.order = self.sell(size=200) # 卖出两百股

fromdate = datetime.datetime(2020, 1, 1)
todate = datetime.datetime(2020, 3, 1)
path = './data/historical/BTC-USDT-SWAP_15m.csv'
# 读取 CSV 文件
df = pd.read_csv(path, parse_dates=['datetime'], index_col='datetime')
print(f"数据的最小日期: {df.index.min()}")
print(f"数据的最大日期: {df.index.max()}")

# 创建 cerebro 引擎

# 将 Pandas DataFrame 转换为 Backtrader 数据
data = bt.feeds.PandasData(dataname=df, fromdate=fromdate, todate=todate)
# if len(data) <2:
#     raise ValueError(f"数据不足，至少需要2条K线数据！当前只有 {len(data)} 条")
if len(data)<3:

    print(len(data),'ssss')
cerebro = bt.Cerebro()
# 
# 添加数据到 cerebro
cerebro.adddata(data)
# print(data.datetime)
# 添加策略
cerebro.addstrategy(TestStrategy)
if len(data)<3:

    print(len(data),'ssss')
# 运行回测
cerebro.run()
if len(data)<3:
    print(len(data),'ssss')
# 绘制结果
# cerebro.plot()
